using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Services.Analytics;
using UnityEngine;

namespace Gj
{

    public interface AnalyticsAdapt
    {
        void Event(string type, Dictionary<string, object> param = null);
        void Purchase(string productId, float price, Dictionary<string, object> param = null);
    }
    
    public class AnalyticsManager: GameManager
    {
        [System.Serializable]
        public enum AnalyticsProvider
        {
            Unity,
            TapDB,
        }

        public static Dictionary<AnalyticsProvider, string> DefinePlatform = new Dictionary<AnalyticsProvider, string>
        {
            {AnalyticsProvider.Unity, "unity"},
            {AnalyticsProvider.TapDB, "tapdb"},
        };
        public struct EventMessage
        {
            public string type;
            public Dictionary<string, object> param;
        }

        public static AnalyticsManager Instance;
        public static AnalyticsSettings settings;
        public static Dictionary<string, object> eventParam;
        public static List<AnalyticsProvider> allow;
        public static bool Ignore;
        public static Dictionary<AnalyticsProvider, AnalyticsAdapt> map = new Dictionary<AnalyticsProvider, AnalyticsAdapt>();
        public static ConcurrentQueue<EventMessage> eventQueue = new ConcurrentQueue<EventMessage>();

        static AnalyticsManager()
        {
            settings = LoadSettings();
        }
        public static void BindAllow(List<AnalyticsProvider> include)
        {
            allow = include;
        }

        public static void Init()
        {
            Instance = new AnalyticsManager();
            eventParam = new Dictionary<string, object>();
            eventParam.Add("Version", Game.GetVersion());
            eventParam.Add("Platform", Game.GetPlatform());
            eventParam.Add("Device", Game.GetDevice());
            
            // 初始化操作
            if (settings.unity && allow.Contains(AnalyticsProvider.Unity))
            {
                map.Add(AnalyticsProvider.Unity, new UnityAnalytics());
            }

            if (settings.tapDB && allow.Contains(AnalyticsProvider.TapDB))
            {
                map.Add(AnalyticsProvider.TapDB, new TapDBAnalytics());
            }

            Game.single.RegisterManager(Instance);
        }
        
        private static AnalyticsSettings LoadSettings()
        {
            AnalyticsSettings loadedSettings = (AnalyticsSettings)Resources.Load("AnalyticsSettings", typeof(AnalyticsSettings));
            if (loadedSettings == null)
            {
                loadedSettings = ScriptableObject.CreateInstance<AnalyticsSettings>();
                LogTools.Error("AnalyticsSettings is not exist (Resources)");
            }
            return loadedSettings;
        }

        public static void RegisterDefault(string key, string value)
        {
            eventParam.Add(key, value);
        }
        
        public static void Event(string type, Dictionary<string, object> param = null)
        {
            LogTools.Log("event:"+type);
            // if (Ignore) return;
            if (param == null)
            {
                param = eventParam;
            }
            else
            {
                var ee = eventParam.GetEnumerator();
                while (ee.MoveNext())
                {
                    param.TryAdd(ee.Current.Key, ee.Current.Value);
                }
                ee.Dispose();
            }
            eventQueue.Enqueue(new EventMessage()
            {
                type = type,
                param = param,
            });
        }

        public static void Send()
        {
            EventMessage message;
            while (eventQueue.TryDequeue(out message))
            {
                var e = map.GetEnumerator();
                while (e.MoveNext())
                {
                    try
                    {
                        e.Current.Value.Event(message.type, message.param);
                    }
                    catch (Exception error)
                    {
                        Debug.LogException(error);
                    }
                }
                e.Dispose();
            }
        }

        public static void Purchase(string productId, float price, Dictionary<string, object> param = null)
        {
            if (Ignore) return;
            var e = map.GetEnumerator();
            while (e.MoveNext())
            {
                e.Current.Value.Purchase(productId, price, param);
            }
            e.Dispose();
        }

        public void OnInit()
        {
        }

        public Task OnUpdate()
        {
            Send();
            return Task.Delay(0);
        }

        public void OnDestroy()
        {
        }

        public void OnPage(BasePage page)
        {

        }
    }

    public class UnityAnalytics : AnalyticsAdapt
    {
        public UnityAnalytics()
        {
            AnalyticsService.Instance.StartDataCollection();
        }
        public void Event(string type, Dictionary<string, object> param)
        {
            // AnalyticsService.Instance.CustomData(type, param);
        }

        public void Purchase(string productId, float price, Dictionary<string, object> param)
        {
            // AnalyticsService.Instance.Transaction(new TransactionParameters()
            // {
            //     ProductID = productId,
            // });
        }
    }
    public class TapDBAnalytics : AnalyticsAdapt
    {
        public TapDBAnalytics()
        {

        }
        public void Event(string type, Dictionary<string, object> param)
        {
            TapTap.TapTap.Event(type, param);
        }

        public void Purchase(string productId, float price, Dictionary<string, object> param)
        {

        }
    }
}